package api

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/jiedan/student-web/server/model"
	"github.com/jiedan/student-web/server/service"
	"gorm.io/gorm"
)

// StudentHandler 学生处理器
type StudentHandler struct {
	DB *gorm.DB
}

// NewStudentHandler 创建学生处理器
func NewStudentHandler(db *gorm.DB) *StudentHandler {
	return &StudentHandler{DB: db}
}

// GetStudents 获取所有学生
func (h *StudentHandler) GetStudents(c *gin.Context) {
	var students []model.Student
	result := h.DB.Preload("User").Preload("User.Role").Find(&students)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get students"})
		return
	}

	// 获取每个学生的总学分
	studentService := service.NewStudentService(h.DB)
	for i := range students {
		totalCredits, err := studentService.GetStudentTotalCredits(students[i].ID)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to calculate total credits"})
			return
		}
		students[i].TotalCredits = totalCredits
	}

	c.JSON(http.StatusOK, students)
}

// GetStudent 获取单个学生
func (h *StudentHandler) GetStudent(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	var student model.Student
	result := h.DB.Preload("User").Preload("User.Role").First(&student, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 获取学生的总学分
	studentService := service.NewStudentService(h.DB)
	totalCredits, err := studentService.GetStudentTotalCredits(student.ID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to calculate total credits"})
		return
	}
	student.TotalCredits = totalCredits

	c.JSON(http.StatusOK, student)
}

// CreateStudentRequest 创建学生请求
type CreateStudentRequest struct {
	UserID uint   `json:"user_id" binding:"required"`
	Class  string `json:"class"`
}

// CreateStudent 创建学生
func (h *StudentHandler) CreateStudent(c *gin.Context) {
	var req CreateStudentRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 创建学生服务
	studentService := service.NewStudentService(h.DB)

	// 创建学生记录
	student, err := studentService.CreateStudent(req.UserID, req.Class)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"message": "Student created successfully", "student": student})
}

// UpdateStudentRequest 更新学生请求
type UpdateStudentRequest struct {
	Class string `json:"class"`
}

// UpdateStudent 更新学生
func (h *StudentHandler) UpdateStudent(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	var req UpdateStudentRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
		return
	}

	// 查找学生
	var student model.Student
	result := h.DB.First(&student, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 更新学生信息
	if req.Class != "" {
		student.Class = req.Class
	}

	// 保存更新
	result = h.DB.Save(&student)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update student"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Student updated successfully"})
}

// DeleteStudent 删除学生
func (h *StudentHandler) DeleteStudent(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid student ID"})
		return
	}

	// 查找学生
	var student model.Student
	result := h.DB.First(&student, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Student not found"})
		return
	}

	// 开始事务
	tx := h.DB.Begin()

	// 删除学生的选课记录
	if err := tx.Where("student_id = ?", id).Delete(&model.CourseSelection{}).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete student's course selections"})
		return
	}

	// 删除学生的成绩记录
	if err := tx.Where("student_id = ?", id).Delete(&model.Grade{}).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete student's grades"})
		return
	}

	// 删除学生记录
	if err := tx.Delete(&student).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete student"})
		return
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to commit transaction"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Student deleted successfully"})
}